// 目标：解决循环引用的问题，检测到循环引用直接抛出错误：如果 then 方法返回的是自己的 Promise 对象，则会发生循环调用，这个时候程序会报错：
//       未捕获（在promise中）类型错误：检测到promise的链接周期#<promise> 

// 思路：在MyPromise4中的 resolvePromise中新增加参数，也就是.then 新建立的promise,与其回调函数进行比较，若完成相等则是循环引用抛出错误。
//          但是这样做依旧会报错，需要在resolvePromise(promise2, x, resolve, reject) 等待  const promise2 = new MyPromise5((resolve, reject) 
//          promise2 的初始化创建，这样才能比较x===mypromise2
//  这时候就需要创建一个异步函数去等待 promise2 完成初始化，然后完成比较。


const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECT = 'reject'

class MyPromise5 {
    constructor(executor) {
        executor(this.resolve, this.reject)
    }

    status = PENDING;

    value = null;

    reason = null;


    onFulfilledCallbacks = [];

    onRejectedCallbacks = [];

    resolve = (value) => {
        if (this.status === PENDING) {
            this.status = FULFILLED;
            this.value = value;

            while (this.onFulfilledCallbacks.length) {
                this.onFulfilledCallbacks.shift()(value)
            }
        }
    }

    reject = (reason) => {
        if (this.status === PENDING) {
            this.status = REJECT;
            this.reason = reason;

            while (this.onRejectedCallbacks.length) {
                this.onRejectedCallbacks.shift()(reason)
            }
        }
    }


    then(onFulfilled, onRejected) {

        const promise2 = new MyPromise5((resolve, reject) => {
            if (this.status === FULFILLED) {
                // 创建一个微任务等待 promise2 完成初始化
                queueMicrotask(() => {
                    // 获取成功回调函数的执行结果
                    const x = onFulfilled(this.value);
                    // 传入 resolvePromise 集中处理
                    resolvePromise(promise2, x, resolve, reject);
                })

            } else if (this.status === REJECT) {

                onRejected(this.reason);
            } else if (this.status === PENDING) {

                this.onFulfilledCallbacks.push(onFulfilled);
                this.onRejectedCallbacks.push(onRejected);

            }
        })
        return promise2;
    }



}

function resolvePromise(promise2, x, resolve, reject) {

    // 如果相等了，说明return的是自己，抛出类型错误并返回
    if (x === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise5) {

        x.then(resolve, reject)
    } else {

        resolve(x)
    }
}

const promise = new MyPromise5((resolve, reject) => {
    resolve(100)
})

let p1 = promise.then(value => {
    console.log(value)
})

let p2 = promise.then(value => {
    console.log(value)
    return p1
})

